/*
 * ContentParser : Given the raw Hashtree object, parsing full tree, and
 * set all content which containing the variable referencing to other variable
 * 
 * Parsing rule
 *     r1 - when encountering the following type of attribute, no parsing
 *         1) name starting with 'ref'
 *         2) name is 'parameter'
 *     r2 - parse by FourFundamentalOperation when content contains '@'
 *     
 *         done by JohnLee in 2013/6/29
 */
package lee.base.xml;
import java.util.HashMap;
import lee.base.constant.ErrorMsg;
import lee.base.constant.Symbol;
import lee.base.constant.XmlAttribute;
import lee.base.structure.MyHashTree;
import lee.base.structure.MyNode;

public class ContentParser {
	
	private MyHashTree treeHead = null;
	protected FourFundamentalOperation ffp = null;
	protected boolean isNeedReparse = false;
	/**
	 * Constructor : ContentParser
	 */
	public ContentParser() {
		this.ffp = new FourFundamentalOperation();
	}
	/**
	 * check and parsing current node if needed when at leave, otherwise, 
	 * go to next child-node
	 * @param curNode - MyNode
	 */
	protected void _001_parseNode(MyNode curNode) {
		if(_002_isNeedParseAttr(curNode.GET003_attribute())) {  //check whether the node need to be parsed
			HashMap<String, MyNode> next = curNode.GET004_next();
			if(next == null) {  //at leave
				this._004_doParse(curNode);
			}
			else {  //at node
				int index = 0;
				String[] keySet = next.keySet().toArray(new String[next.keySet().size()]);
				while(index < keySet.length) {
					this._001_parseNode(next.get(keySet[index]));
					index = index + 1;
				}
			}
		}
	}
	/**
	 * check whether the content of passing attribute need to be parsed
	 * @param attrName - String
	 * @return true/false
	 */
	protected boolean _002_isNeedParseAttr(String attrName) {
		return (!attrName.startsWith(XmlAttribute.REFERENCE_ATTR_NAME_START)) &&
			   (attrName.compareTo(XmlAttribute.PAPRMETER_ATTR_NAME) != 0);
	}
	/**
	 * check whether the content need to be parsed
	 * @param content
	 * @return true/false
	 */
	protected boolean _003_isNeedParseContent(String content) {
		return content.contains(XmlAttribute.VARIABLE_POINT + "");
	}
	/**
	 * do full parsing, if there exists any variable content for current node
	 * and all of it's child when finishing, mark isNeedReparse to true
	 * @param parseNode - MyNode
	 */
	protected void _004_doParse(MyNode parseNode) {
		String getContent = parseNode.GET001_value();
		if(this._003_isNeedParseContent(getContent)) {
			String newResult = this.ffp.ACT001_operate(getContent, this.treeHead);
			if(newResult.compareTo(ErrorMsg.MSG_GET_CONTENT_VARIABLE) != 0) {  //the content is a constant not a type of variable
				parseNode.SET001_value(newResult);
			}
			else {
				this.isNeedReparse = true;
			}
		}
	}
	/**
	 * parsing the full tree and let all content to constant value
	 * @param treeHead - MyHashTree
	 */
	public void ACT001_parseFullTree(MyHashTree treeHead) {
		this.treeHead = treeHead;
		//get head node
		MyNode nodeHead = this.treeHead.ACT006_getHeadNode();
		//start to parse and modify content for each node if needed, if existing any content 
		//being a variable, do reparse when finishing one round
		this.isNeedReparse = true;
		while(this.isNeedReparse) {
			this.isNeedReparse = false;
			this._001_parseNode(nodeHead);
		}
	}
}
